<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Dep</title>
</head>
<body>
  <div>思路分析中，需要创建一个可以容纳订阅者的消息订阅器Dep，订阅器Dep主要负责收集订阅者，然后再属性变化的时候执行对应订阅者的更新函数。
    所以显然订阅器需要有一个容器，这个容器就是list，将上面的Observer稍微改造下，植入消息订阅器</div>
</body>

<script>
   function defineReactive(data, key, val) {
    observer(val); // 递归遍历所有子属性
    var dep = new Dep(); 
    Object.defineProperty(data, key, {
      get: function() {
        // if (true) {
        //   dep.addSub(watcher); // 在这里添加一个订阅者
        // }
        return val // get一定要return
      },
      set: function(newValue) {
        if (val === newValue) {
          return;
        }
        val = newValue;
        // console.log("要改的属性", key, "已经被监听的值", newValue)
        console.log('属性' + key + '已经被监听了，现在值为：“' + newValue.toString() + '”');
        dep.notify(); // 如果数据变化，通知所有订阅者
      }
    })
  }


  function observer(data) {
    // 必须是一个对象
    if(!data || typeof data !== "object") {
      return 
    }
    // Object.keys 遍历数组和对象 key 值， 并排序, 返回数组
    // forEach 数组遍历，依次输出每个数组值
    Object.keys(data).forEach(function(key){
      // forEach在这里遍历每个对象 key是比较的属性
      defineReactive(data, key, data[key])
    })
  }

  function Dep () {
    this.subs = [];
  }
  Dep.prototype = {
    addSub: function(sub) {
        this.subs.push(sub);
    },
    notify: function() {
      this.subs.forEach(function(sub) {
        sub.update();
      });
    }
  };

  var library = {
    book1: {
        name: ''
    },
    book2: ''
  };

  observer(library);
  library.book1.name = 'vue权威指南'; // 属性name已经被监听了，现在值为：“vue权威指南”
  library.book2 = '没有此书籍'; 
 
</script>
</html>